#include "ShaderProgram.h"
#include "Exception.h"

NS_B2D_BEGIN

Shader::Shader(ShaderType type)
	: mType(type)
	, mIsCompiled(false)
	, mSource(nullptr)
	, mSourceSize(0)
{
	
}

Shader::~Shader(void)
{
	// Delete source
	if( mSource != nullptr )
		SafeDeleteArray(mSource);
}


void Shader::compileWithSource(const char* src)
{
	compileWithSource( src, strlen(src) );
}

void Shader::compileWithSource(const char* src, size_t len)
{
	// Clear previous data
	if( mIsCompiled == true )
	{
		SafeDeleteArray(mSource);
		mIsCompiled = false;
	}
	
	// Set source
	mSourceSize = len +1; // null ending
	mSource = new char[mSourceSize];
	mSource[len] = 0;
	memcpy(mSource, src, mSourceSize);

	// Compile
	compileImpl();
	mIsCompiled = true;
}



//
// ShaderProgram
//

B2D_RESOURCE_IMPL(IShaderProgram, IResource)
B2D_OBJECT_IMPL(ShaderProgram, IShaderProgram)

ShaderProgram::ShaderProgram(void)
	: mNeedsRelinking(true)
	, mLinked(false)
{
	memset(mShaders, 0, sizeof(mShaders));
}

ShaderProgram::~ShaderProgram(void)
{
	
}

Shader* ShaderProgram::operator[] (ShaderType type) const
{
	return getShader(type);
}


Shader* ShaderProgram::addShader(ShaderType type)
{
	size_t t = static_cast<size_t>(type);
	Shader* shader =  mShaders[t];
	if( shader == nullptr )
	{
		shader = addShaderImpl(type);
		mShaders[t] = shader;
		mNeedsRelinking = true;
	}
	return shader;
}

void ShaderProgram::removeShader(ShaderType type)
{
	size_t t = static_cast<size_t>(type);
	Shader* shader =  mShaders[t];
	if( shader != nullptr )
	{
		removeShaderImpl(shader);
		SafeDelete(shader);
		mShaders[t] = nullptr;
		mNeedsRelinking = true;
	}
}

Shader* ShaderProgram::getShader(ShaderType type) const
{
	return mShaders[static_cast<size_t>(type)];
}

void ShaderProgram::link(void)
{
	if( isInitialised() != true )
	{
		B2D_THROW(Exception::GRAPHICS_API_EXCEPTION,
			"Can not link shader program\""+mName.getString()+"\" because it hasnt been initialised.");
	}
	
	linkImpl();
	mNeedsRelinking = false;
	mLinked = true;
}


NS_B2D_END